package com.baizhi.utils;

import cn.hutool.core.util.ObjectUtil;
import com.baizhi.dto.Result;
import com.baizhi.entity.Shop;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;
import java.util.function.Function;

@Component
public class CacheClient {
    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * 利用互斥锁到缓存li面查询数据 避免缓存击穿 如过缓存中没有要到数据库中查询 并放到缓存中
     * @param id  查询条件
     * @return 要缓存的对象
     * @param <R> 返回值类型
     * @param <T>  查询条件的类型
     */
    public <R,T> R queryWithMutex (T id, String redisPrefix, Function<T,R> function,Long ttl,TimeUnit unit){
        //1 先到redis里面获取数据是否能获取到
        //1.1 生成key
        String key = redisPrefix+id;
        //1.2 根据key获取数据
        R r = (R) redisTemplate.opsForValue().get(key);
        //2.true 如果查到直接返回
        if (ObjectUtil.isNotEmpty(r)){
            return r;
        }
        //2.false
        synchronized (this){
            //2.1 在查一遍
            r = (R) redisTemplate.opsForValue().get(key);
            if (ObjectUtil.isNotEmpty(r)){
                return r;
            }
            //3 如果没有拿到 则调用数据库拿数据
            R apply = function.apply(id);
            if (ObjectUtil.isEmpty(apply)){
                return null;
            }
            redisTemplate.opsForValue().set(key,apply,ttl,unit);
            return apply;
        }
    }
}
